﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using GDepth;
using ConvexHull;

namespace GromovGUI
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// This form display good/bad directions for the point clicked
        /// </summary>
        System.Drawing.Graphics gd;
        
        //G Depth class
        Class1 cls;
        frmConvexHull ch_class = new frmConvexHull();
        double UnitArea;
        
        int NumberOfPoints, DepthContourSize;
        double CurrentX, CurrentY;
        //end data
        PointF[] Points;
        PointF[] DepthContour;
        StreamReader PointsStream, contStream;
        double depth;
        
        public Form1()
        {
            InitializeComponent();
            cls = new Class1();

            PointsStream = new StreamReader("dp1.txt");
            contStream = new StreamReader("contour.txt");
            gd = this.CreateGraphics();
            ReadPointSet();
            ReadDepthContour();
            PointsStream.Close();
            contStream.Close();
        }

        private void ReadPointSet()
        {
            Points = new PointF[200];
            NumberOfPoints = Convert.ToInt32(PointsStream.ReadLine());
            NumberOfPoints = Convert.ToInt32(PointsStream.ReadLine());
            int i;
            for (i = 0; i < NumberOfPoints; i++)
            {
                //TODO: depending upon input of query point normalize the point set.
                Points[i].X = Convert.ToInt32(Convert.ToDouble(PointsStream.ReadLine()) + 300);
                Points[i].Y = 300;
                Points[i].Y -= (Convert.ToInt32(Convert.ToDouble(PointsStream.ReadLine())));
                /*
                Points[i].X = Convert.ToInt32(Convert.ToDouble(PointsStream.ReadLine()));                
                Points[i].Y = (Convert.ToInt32(Convert.ToDouble(PointsStream.ReadLine())));
                 * */
                ch_class.addPoint(Points[i]);
            }
            UnitArea = ch_class.AreaOfConvexHull();
            depth = Convert.ToDouble(PointsStream.ReadLine());
        }

        private void ReadDepthContour()
        {
            DepthContour = new PointF[200];
            DepthContourSize = Convert.ToInt32(contStream.ReadLine());

            for (int i = 0; i < DepthContourSize; i++)
            {

                DepthContour[i].X = Convert.ToInt32(Convert.ToDouble(contStream.ReadLine()) + 300);
                DepthContour[i].Y = 300;
                DepthContour[i].Y -= (Convert.ToInt32(Convert.ToDouble(contStream.ReadLine())));
            }
        }

        private void DrawDepthContour()
        {
            for (int i = 0; i < DepthContourSize; i++)
            {
                if (i == DepthContourSize - 1)
                    gd.DrawLine(Pens.Black, DepthContour[i], DepthContour[0]);
                else
                    gd.DrawLine(Pens.Black, DepthContour[i], DepthContour[i + 1]);
            }
        }


        private void PlotPointSet(int width = 4, int height = 4)
        {
            for (int i = 0; i < NumberOfPoints; i++)
            {
                gd.FillRectangle(Brushes.DarkRed, Points[i].X - (width / 2), Points[i].Y - (height / 2), width, height);
            }
        }

        private void RedrawForNewPoint()
        {
            gd.Clear(Color.White);
            PlotPointSet();
            DrawDepthContour();


            //TODO: CHeck it out yar
            Point ptr, p2;
            ptr = new Point();
            p2 = new Point();


            p2.X =Convert.ToInt32( CurrentX)+300;
            p2.Y = 300 - Convert.ToInt32(CurrentY);

            label1.Text = cls.Depth(CurrentX, CurrentY).ToString();
            ptr.X = 300 + cls.GetXDirection();
            ptr.Y = 300 - (cls.GetYDirection());

            StreamReader sr2 = new StreamReader("dump.txt");
            Point[] arr = new Point[3];
            arr[0] = p2;

            for (int i = 0; i < NumberOfPoints; i++)
            {

                int flag = Convert.ToInt32(sr2.ReadLine());
                double x1, y1;
                x1 = Convert.ToDouble(sr2.ReadLine());
                y1 = Convert.ToDouble(sr2.ReadLine());
                arr[1].X = Convert.ToInt32(x1) + 300;
                arr[1].Y = 300 - Convert.ToInt32(y1);

                x1 = Convert.ToDouble(sr2.ReadLine());
                y1 = Convert.ToDouble(sr2.ReadLine());
                arr[2].X = Convert.ToInt32(x1) + 300;
                arr[2].Y = 300 - Convert.ToInt32(y1);

                if (flag == 1)
                    gd.FillPolygon(Brushes.Aqua, arr);
                else
                    gd.FillPolygon(Brushes.Red, arr);

            }
            gd.DrawLine(Pens.Black, p2, ptr);
            sr2.Close();
            PlotPointSet();
            DrawDepthContour();  


        
        }

        private double distance(PointF a,PointF b)
        {
            double sum = Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));

            return sum;            
        }
        private double vector_normalizer()
        {
            double total=0;
            for (int i = 0; i < NumberOfPoints; i++)
            {
                for (int j = 0; j < NumberOfPoints; j++)
                    total += distance(Points[i], Points[j]);

            }

            return total;
        
        }
        private double vector_depth()
        {

            double sum = 0;
            PointF tt = new PointF( Convert.ToInt32( CurrentX), Convert.ToInt32(CurrentY));
            for (int i = 0; i < NumberOfPoints; i++)
            {
                sum+=distance(tt, Points[i]);            
            }
            return sum/vector_normalizer();
        
        }

        private double minimize()
        {
            //double min = 100000000;
            double min =0;
            double n = 100, id=0;
            double sum = 0;
            for (int k = 0; k < n; k++)
            {
                sum = n * n * n / ((n - k) * (n - k)*32);
                if (sum > min)
                {
                    min = sum;
                    id = k;
                
                }
            }

            return 0;        
        }
        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            //test
            //minimize();
            //TODO: Normalize
            
            CurrentX = e.X - 300;
            CurrentY = 300 - (e.Y);
            
            /*
            CurrentX = e.X ;
            CurrentY = 600-e.Y;
            CountArea();
            label5.Text = vector_depth().ToString();

            CurrentX = e.X - 300;
            CurrentY = 300 - (e.Y);
            */

            RedrawForNewPoint();            
            //PlotPointSet();
            

        }
        private double AreaofTriangle(int i, int j)
        {
            double area = 0;
            area += Points[i].X * ((300-Points[j].Y) - (CurrentY));
            area += Points[j].X * ((CurrentY) - (300-Points[i].Y));
            area += (CurrentX) * ((300 - Points[i].Y) - (300 - Points[j].Y));
            if (area < 0)
                area = area * -1;
            return area/2;
 
        
        }
        private void CountArea()
        {
            double area = 0;
            double ratio;
            for (int i = 0; i < NumberOfPoints; i++)
                for (int j = i+1; j < NumberOfPoints; j++)
                { 
                    area += AreaofTriangle(i,j);                
                }

            ratio = area / UnitArea;
            ratio =ratio / (NumberOfPoints*NumberOfPoints);
            ratio = 1 / ratio;
            label4.Text = ratio.ToString();        
        }


        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up: CurrentY++; RedrawForNewPoint(); ; break;
                case Keys.Down: CurrentY--; RedrawForNewPoint(); ; break;
                case Keys.Left: CurrentX--; RedrawForNewPoint(); ; break;
                case Keys.Right: CurrentX++; RedrawForNewPoint(); ; break;
                case Keys.S: if (e.Control) SaveToFile(); break;
                case Keys.L: if (e.Control) LoadFromFile(); break;
                case Keys.O: if (e.Control) LoadFromFile(); break;
            
            }
            
        }

        private void SaveToFile()
        {
            FileDialog fd = new SaveFileDialog();
            fd.DefaultExt = "txt";
            fd.ShowDialog();
            StreamWriter SaveStream = new StreamWriter(fd.FileName);
            SaveStream.WriteLine(NumberOfPoints);
            for (int i = 0; i < NumberOfPoints; i++)
            {
                SaveStream.WriteLine(Points[i].X);
                SaveStream.WriteLine(Points[i].Y);
            }
            SaveStream.WriteLine(DepthContourSize);

            for (int i = 0; i < DepthContourSize; i++)
            {
                SaveStream.WriteLine(DepthContour[i].X);
                SaveStream.WriteLine(DepthContour[i].Y);
            }
            SaveStream.WriteLine(CurrentX);
            SaveStream.WriteLine(CurrentY);
            fd.Dispose();
            SaveStream.Close();
            SaveStream.Dispose();        
        }
        private void LoadFromFile()
        {
            FileDialog fd = new OpenFileDialog();
            fd.DefaultExt = "txt";
            fd.ShowDialog();
            StreamReader OpenStream = new StreamReader(fd.FileName);
            NumberOfPoints = Convert.ToInt32(OpenStream.ReadLine());
            for (int i = 0; i < NumberOfPoints; i++)
            {
                Points[i].X = Convert.ToInt32(OpenStream.ReadLine());
                Points[i].Y = Convert.ToInt32(OpenStream.ReadLine());
            }
            DepthContourSize = Convert.ToInt32(OpenStream.ReadLine());

            for (int i = 0; i < DepthContourSize; i++)
            {
                DepthContour[i].X = Convert.ToInt32(OpenStream.ReadLine());
                DepthContour[i].Y = Convert.ToInt32(OpenStream.ReadLine());
            }

            CurrentX = Convert.ToInt32(OpenStream.ReadLine());
            CurrentY = Convert.ToInt32(OpenStream.ReadLine());
            RedrawForNewPoint();
            OpenStream.Close();
            OpenStream.Dispose();
            fd.Dispose();

        }
        private void button1_Click(object sender, EventArgs e)
        {
        
        }

        private void button2_Click(object sender, EventArgs e)
        {
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void label3_Click(object sender, EventArgs e)
        {

        }
    }
}
